package module.library.speech;

import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.os.Environment;
import android.support.v4.app.FragmentManager;
import android.util.Log;
import android.view.View;

import com.iflytek.cloud.ErrorCode;
import com.iflytek.cloud.InitListener;
import com.iflytek.cloud.RecognizerListener;
import com.iflytek.cloud.RecognizerResult;
import com.iflytek.cloud.SpeechConstant;
import com.iflytek.cloud.SpeechError;

import library.common.view.dialog.CommonDialog;
import library.common.view.dialog.CommonDialogFragment;
import library.common.view.dialog.base.CommonParams;
import library.common.view.dialog.base.IDialogCreator;

/**
 * @author Created by qiang.hou on 2018/9/6.
 * @version 1.0
 */
public class SpeechRecognizer {

    private SpeechRecognizer() {
    }

    private static class SingleInstanceHolder {
        static final SpeechRecognizer INSTANCE = new SpeechRecognizer();
    }

    public static SpeechRecognizer getInstance() {
        return SingleInstanceHolder.INSTANCE;
    }

    /**
     * 语音听写对象
     */
    private com.iflytek.cloud.SpeechRecognizer speechRecognizer;
    private boolean isSpeeching = false;

    private Dialog dialog;
    private Context context;
    private FragmentManager fragmentManager;
    private ISpeechCallback speechCallback;
    private int controlButtonId = -1;
    private int speechDialogLayoutId = -1;

    public SpeechRecognizer dialog(Dialog dialog) {
        this.dialog = dialog;
        return this;
    }

    public SpeechRecognizer context(Context Context) {
        this.context = context;
        return this;
    }

    public SpeechRecognizer fragment(FragmentManager fragmentManager) {
        this.fragmentManager = fragmentManager;
        return this;
    }

    public SpeechRecognizer speechDialogLayoutId(int speechDialogLayoutId) {
        this.speechDialogLayoutId = speechDialogLayoutId;
        return this;
    }

    public SpeechRecognizer controlButtonId(int controlButtonId) {
        this.controlButtonId = controlButtonId;
        return this;
    }

    public SpeechRecognizer speechCallback(ISpeechCallback speechCallback) {
        this.speechCallback = speechCallback;
        return this;
    }

    public void start() {
        if (null == context) {
            if (null != dialog) {
                this.context = dialog.getContext();
            } else {
                return;
            }
        }

        if (null == dialog) {
            if (speechDialogLayoutId > 0 && controlButtonId > 0) {
                initSpeech(context);
                if (null != fragmentManager) {
                    new CommonDialogFragment.Builder()
                            .layoutId(speechDialogLayoutId)
                            .setOnClickListener(new View.OnClickListener() {
                                @Override
                                public void onClick(View view) {
                                    if (isSpeeching) {
                                        stopSpeechRecognize(speechCallback);
                                    } else {
                                        startSpeechRecognize(speechCallback);
                                    }
                                }
                            }, controlButtonId)
                            .setOnDismissListener(new CommonParams.OnDismissListener() {
                                @Override
                                public void onDismiss(Object result) {
                                    if (null != speechRecognizer) {
                                        // 退出时释放连接
                                        speechRecognizer.cancel();
                                        speechRecognizer.destroy();
                                        speechRecognizer = null;
                                    }
                                }
                            })
                            .create().show(fragmentManager);
                } else {
                    new CommonDialog.Builder()
                            .layoutId(speechDialogLayoutId)
                            .setOnClickListener(new View.OnClickListener() {
                                @Override
                                public void onClick(View view) {
                                    if (isSpeeching) {
                                        stopSpeechRecognize(speechCallback);
                                    } else {
                                        startSpeechRecognize(speechCallback);
                                    }
                                }
                            }, controlButtonId)
                            .setOnDismissListener(new CommonParams.OnDismissListener() {
                                @Override
                                public void onDismiss(Object result) {
                                    if (null != speechRecognizer) {
                                        // 退出时释放连接
                                        speechRecognizer.cancel();
                                        speechRecognizer.destroy();
                                        speechRecognizer = null;
                                    }
                                }
                            })
                            .create().show();
                }
            }

        } else if (controlButtonId > 0) {
            initSpeech(context);
            dialog.findViewById(controlButtonId).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    if (isSpeeching) {
                        stopSpeechRecognize(speechCallback);
                    } else {
                        startSpeechRecognize(speechCallback);
                    }
                }
            });
            if (!dialog.isShowing()) {
                if (null != fragmentManager) {
                    new CommonDialogFragment.Builder()
                            .dialog(new IDialogCreator() {
                                @Override
                                public Dialog createDialog() {
                                    return dialog;
                                }
                            })
                            .setOnDismissListener(new CommonParams.OnDismissListener() {
                                @Override
                                public void onDismiss(Object result) {
                                    if (null != speechRecognizer) {
                                        // 退出时释放连接
                                        speechRecognizer.cancel();
                                        speechRecognizer.destroy();
                                        speechRecognizer = null;
                                    }
                                }
                            })
                            .create()
                            .show(fragmentManager);
                } else {
                    /*
                     * dismiss
                     */
                    dialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
                        @Override
                        public void onDismiss(DialogInterface dialogInterface) {
                            if (null != speechRecognizer) {
                                // 退出时释放连接
                                speechRecognizer.cancel();
                                speechRecognizer.destroy();
                                speechRecognizer = null;
                            }
                        }
                    });
                    dialog.show();
                }
            }
        } else {
            Log.i("SpeechRecognizer", "no controlId");
        }
    }

    /**
     * start
     *
     * @param speechCallback ISpeechCallback
     */
    private void startSpeechRecognize(final ISpeechCallback speechCallback) {
        int result = speechRecognizer.startListening(new RecognizerListener() {
            @Override
            public void onVolumeChanged(int volume, byte[] data) {
                Log.i("SpeechRecognizer", "返回音量数据：" + volume);
                if (null != speechCallback) {
                    speechCallback.onVoice(volume);
                }
            }

            @Override
            public void onBeginOfSpeech() {
                // 此回调表示：sdk内部录音机已经准备好了，用户可以开始语音输入
                Log.i("SpeechRecognizer", "onBeginOfSpeech");
                isSpeeching = true;
                if (null != speechCallback) {
                    speechCallback.onStartInput();
                }
            }

            @Override
            public void onEndOfSpeech() {
                // 此回调表示：检测到了语音的尾端点，已经进入识别过程，不再接受语音输入
                Log.i("SpeechRecognizer", "onEndOfSpeech");
                isSpeeching = false;
                if (null != speechCallback) {
                    speechCallback.onStop();
                }
            }

            @Override
            public void onResult(RecognizerResult recognizerResult, boolean isLast) {
                Log.i("SpeechRecognizer", "onResult");
                String text = JsonParser.parseIatResult(recognizerResult.getResultString());
                if (null != speechCallback) {
                    speechCallback.onFinishInput(text);
                }
            }

            @Override
            public void onError(SpeechError speechError) {
                // 错误码：10118(您没有说话)，可能是录音机权限被禁，需要提示用户打开应用的录音权限。
                if (null != speechCallback) {
                    speechCallback.onError(speechError.getErrorCode());
                }
            }

            @Override
            public void onEvent(int i, int i1, int i2, Bundle bundle) {

            }
        });
        if (result != ErrorCode.SUCCESS) {
            if (null != speechCallback) {
                speechCallback.onError(result);
            }
        } else {
            if (null != speechCallback) {
                speechCallback.onStart();
            }
        }
    }

    /**
     * stop
     *
     * @param speechCallback ISpeechCallback
     */
    private void stopSpeechRecognize(ISpeechCallback speechCallback) {
        isSpeeching = false;
        speechRecognizer.stopListening();
        if (null != speechCallback) {
            speechCallback.onStop();
        }
    }

    public interface ISpeechCallback {
        /**
         * start
         */
        void onStart();

        /**
         * start input
         */
        void onStartInput();

        /**
         * finish input
         */
        void onFinishInput(String text);

        /**
         * stop
         */
        void onStop();

        /**
         * error
         */
        void onError(int code);

        /**
         * volume change
         */
        void onVoice(int volume);
    }

    /**
     * 初始化
     *
     * @param context Context
     */
    private void initSpeech(Context context) {
        isSpeeching = false;
        speechRecognizer = com.iflytek.cloud.SpeechRecognizer.createRecognizer(context, new InitListener() {

            @Override
            public void onInit(int code) {
                if (code != ErrorCode.SUCCESS) {
                    Log.i("SpeechRecognizer", "语音功能初始化失败，错误码：" + code);
                }
            }
        });
        setParam(speechRecognizer);
    }

    private void setParam(com.iflytek.cloud.SpeechRecognizer speechRecognizer) {
        // 清空参数
        speechRecognizer.setParameter(SpeechConstant.PARAMS, null);
        // 设置引擎
        speechRecognizer.setParameter(SpeechConstant.ENGINE_TYPE, SpeechConstant.TYPE_CLOUD);
        // 设置返回结果格式
        speechRecognizer.setParameter(SpeechConstant.RESULT_TYPE, "json");
        // 设置语言
        speechRecognizer.setParameter(SpeechConstant.LANGUAGE, "zh_cn");
        // 设置语言区域
        speechRecognizer.setParameter(SpeechConstant.ACCENT, "mandarin");

        // 设置语音前端点:静音超时时间，即用户多长时间不说话则当做超时处理
//        speechRecognizer.setParameter(SpeechConstant.VAD_ENABLE, "0");
        speechRecognizer.setParameter(SpeechConstant.VAD_BOS, "100000000000");

        // 设置语音后端点:后端点静音检测时间，即用户停止说话多长时间内即认为不再输入， 自动停止录音
        speechRecognizer.setParameter(SpeechConstant.VAD_EOS, "100000000000");

        // 设置标点符号,设置为"0"返回结果无标点,设置为"1"返回结果有标点
        speechRecognizer.setParameter(SpeechConstant.ASR_PTT, "1");

        // 设置音频保存路径，保存音频格式支持pcm、wav，设置路径为sd卡请注意WRITE_EXTERNAL_STORAGE权限
        speechRecognizer.setParameter(SpeechConstant.AUDIO_FORMAT, "wav");
        speechRecognizer.setParameter(SpeechConstant.ASR_AUDIO_PATH, Environment.getExternalStorageDirectory() + "/msc/iat.wav");
    }
}
